package com.polaris.live.manager

import android.annotation.SuppressLint
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.manager.withDeferred
import com.polaris.live.common.util.LogExt
import com.polaris.live.utils.file.FileUtils.getFilePath
import com.polaris.live.utils.image.ImageUtils
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.launch
import zlc.season.rxdownload4.download
import zlc.season.rxdownload4.task.Task
import java.io.File
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicInteger

/**
 * DownFileManager
 *
 * @author Created by 半仙 on 2023/11/27/027 17:20
 */
object DownFileManager {
    //最大同时下载
    private const val MAX_LOADING = 4

    //用这个也是因为他能保证一个线程安全的队列  高并发的场景性能更好
    //等待下载队列    first = 下载目录      sencond = 文件后续地址      拼在一起就是下载地址
    private val waitingList = ConcurrentLinkedQueue<Pair<String, String>>()

    //当前下载数量  用这个主要是因为他有原子操作和线程安全   原子操作可以让他避免竞争导致的问题
    private val nowNum = AtomicInteger(0)

    suspend fun loadFile(directory: String, path: String) {

        if (File("$directory/$path").exists()) {
            return
        }

        if (nowNum.get() >= MAX_LOADING) {
            waitingList.add(Pair(directory, path))
        } else {
            loadPag(directory, path)
        }
    }

    private suspend fun loadPag(pathDir: String, path: String) {

        val lastSlashIndex = path.lastIndexOf('/')
        val directory = path.substring(0, lastSlashIndex + 1)
        val fileName = path.substring(lastSlashIndex + 1)

        nowNum.incrementAndGet()


        if (File("$directory/$path").exists()) {
            loadNext()
            return
        }

        LogExt.logI("--downLoad") {
            "开始下载 ------ ${ImageUtils.imgPath(path)}"
        }


        withDeferred {
            Task(
                ImageUtils.imgPath(path),
                saveName = fileName,
                savePath = "$pathDir/$directory"
            ).download()
                .subscribe({}, {
                    completeExceptionally(it)
                    LogExt.logI("--downLoad") {
                        "失败   ${it.message}"
                    }
                    loadNext()
                }, {
                    LogExt.logI("--downLoad") {
                        "成功    ${getFilePath(pathDir, path)}"
                    }
                    complete(Unit)
                    loadNext()
                })
        }
    }

    private fun loadNext() {
        nowNum.decrementAndGet()
        CoroutineScopeManager.ioScope.launch {
            waitingList.poll()?.let {
                loadFile(it.first, it.second)
            }
        }
    }

    //==================================================================================================
    //如果你需要自己维护下载队列就用这个，每次下完会回调回去地址  失败了就是空
    @SuppressLint("CheckResult")
    suspend fun loadFileCallback(pathDir: String, path: String): Pair<String, String>? {
        val filePath = getFilePath(pathDir, path)
        if (File(filePath).exists()) {
            return pathDir to path
        }
        val deferred = CompletableDeferred<Pair<String, String>?>()
        //我这里逻辑是如果下载成功或者已经下载过了就会吧你的东西返回，如果下载失败则返回空哈
        LogExt.logI("--downLoad") {
            "开始下载 ------ ${ImageUtils.imgPath(path)}"
        }

        val lastSlashIndex = path.lastIndexOf('/')
        val directory = path.substring(0, lastSlashIndex + 1)
        val fileName = path.substring(lastSlashIndex + 1)
        Task(
            ImageUtils.imgPath(path),
            saveName = fileName,
            savePath = "$pathDir/$directory"
        ).download()
            .subscribe({}, {
                LogExt.logI("--downLoad") {
                    "失败 == $filePath ==  ${it.message}"
                }
                deferred.complete(null)

            }, {
                LogExt.logI("--downLoad") {
                    "成功 == 文件地址： $filePath"
                }
                deferred.complete(pathDir to path)
            })
        return deferred.await()
    }
}
